class: center, middle, inverse, title-slide .title[ # ISA 444: Business Forecasting ] .subtitle[ ## 03: Time Series Plots ] .author[ ###
Fadel M. Megahed, PhD
Endres Associate Professor
Farmer School of Business
Miami University
@FadelMegahed
fmegahed
fmegahed@miamioh.edu
Automated Scheduler for Office Hours
] .date[ ### Spring 2023 ] --- # Quick Refresher from Last Class ✅ Describe the syntax, data types, and data structures in
. ✅ Access the help for
functions (each help file has the following components: Description, usage, arguments, value, and examples). ✅ Utilize the project workflow in
and create
script. ❌ Access, subset, and create `ts()` objects in
. --- # Learning Objectives for Today's Class - Examine a line chart for trends, seasonality, and cycles. - Explain the grammar of graphics and how it can be used to create time series plots in
. - Create interactive time-series plots by using the [plotly](https://plotly.com/ggplot2/getting-started/) package
. --- class: inverse, center, middle # A Taxonomy of Time Series Plots and their Interpretation --- # A Structured Approach for Time Series Viz <div class="figure" style="text-align: center"> <img src="data:image/png;base64,#../../figures/ts_plots.png" alt="A Potential Framework for Time Series Visualization" width="100%" /> <p class="caption">A Potential Framework for Time Series Visualization</p> </div> .footnote[ <html> <hr> </html> This is my best attempt to improve on the general advice provided in the previous slide. Many of the suggestions, presented in this flow chart, stem from my past and current research/consulting collaborations. They are by no means a comprehensive list of everything that you can do. ] --- # The Line Chart .pull-left[ <div class="figure" style="text-align: center"> <img src="data:image/png;base64,#03_ts_viz_files/figure-html/cincyplot1-1.png" alt="A plot of a long time-series for monthly weather in Cincinnati, with color denoting different months." width="100%" /> <p class="caption">A plot of a long time-series for monthly weather in Cincinnati, with color denoting different months.</p> </div> ] .pull-right[ <div class="figure" style="text-align: center"> <img src="data:image/png;base64,#03_ts_viz_files/figure-html/cincyplot2-1.png" alt="A snippet of the time-series (last 5 years) for monthly weather in Cincinnati, with color denoting different months." width="100%" /> <p class="caption">A snippet of the time-series (last 5 years) for monthly weather in Cincinnati, with color denoting different months.</p> </div> ] --- # The Line Chart: Practical Considerations .can-edit.key-activity0_[ **Things to Consider:** .font70[(Insert below)] - **Format your data:** .... - **Entire time-series vs a snippet:** .... - **On the Use of Color:** .... - **On grouping the data:** .... ] --- # On the Interpretation of Line Charts
−
+
05
:
00
.panelset[ .panel[.panel-name[Activity] > Over the next 5 minutes, please identify what you have learned from the charts in each tab. - Write down your answers in the last tab (it is editable). - Discuss your answers with your neighboring classmates. - Be prepared to share these answers with class. ] .panel[.panel-name[Book Stores] <center> <iframe src="https://fred.stlouisfed.org/graph/graph-landing.php?g=ZopX&width=800&height=450" scrolling="no" frameborder="0" style="overflow:hidden; width:800px; height:500px;" allowTransparency="true" loading="lazy"></iframe> </center> ] .panel[.panel-name[GDP 1] <center> <iframe src="https://fred.stlouisfed.org/graph/graph-landing.php?g=ZorB&width=800&height=450" scrolling="no" frameborder="0" style="overflow:hidden; width:800px; height:500px;" allowTransparency="true" loading="lazy"></iframe> </center> ] .panel[.panel-name[GDP 2] <center> <iframe src="https://fred.stlouisfed.org/graph/graph-landing.php?g=ZorL&width=800&height=450" scrolling="no" frameborder="0" style="overflow:hidden; width:800px; height:500px;" allowTransparency="true" loading="lazy"></iframe> </center> ] .panel[.panel-name[Key Points] .can-edit.key-activity0b_viz[ **Main Insight(s):** .font70[(Insert below)] - **Book Stores:** Trend: ... | Seasonality: ... | Cycle: ... - **GDP 1:** Trend: ... | Seasonality: ... | Cycle: ... - **GDP 2:** Trend: ... | Seasonality: ... | Cycle: ... ] ] ] --- # Need Assistance with Trends <img src="data:image/png;base64,#03_ts_viz_files/figure-html/trends-1.png" width="70%" style="display: block; margin: auto;" /> --- # Need Assistance with Seasonality In [Section 2.2.1 of our reference book](https://wessexlearning.com/products/principles-of-business-forecasting-2nd-ed-part-i), the authors presented two approaches for considering seasonality. We can replicate them easily in R. Refer to the discussion in the next section for more detail. --- class: inverse, center, middle # The Grammar of Graphics and the `ggplot2` package --- # A Visual Introduction to Graph Layers <div class="figure" style="text-align: center"> <img src="data:image/png;base64,#https://r.qcbs.ca/workshop03/book-en/images/Layers_ggplot.png" alt="The package ggplot2 is based on the Grammar of Graphics (GG), which is a framework for data visualization that dissects each component of a graph into individual components, creating distinct layers. Using the GG system, we can build graphs step-by-step for flexible, customizable results." width="100%" /> <p class="caption">Schematic of some distinct layers in the Grammar of Graphics.</p> </div> .footnote[ <html> <hr> </html> Figure from the QCBS R Workshop Series. It is from [Chapter 05 of their third workshop](https://r.qcbs.ca/workshop03/book-en/grammar-of-graphics-gg-basics.html). ] --- # The Grammar of Graphics <div class="figure" style="text-align: center"> <img src="data:image/png;base64,#https://r.qcbs.ca/workshop03/book-en/images/gglayers.png" alt="An overview of the layers highlighted in the Grammar of Graphics." width="57%" /> <p class="caption">An overview of the layers introduced in the Grammar of Graphics.</p> </div> .footnote[ <html> <hr> </html> Figure from the QCBS R Workshop Series. It is from [Chapter 05 of their third workshop](https://r.qcbs.ca/workshop03/book-en/grammar-of-graphics-gg-basics.html). ] --- # Grammar of Graphics Layers: Data - Data needs to be in a **tidy** format (see next two slides). - The [dplyr](https://dplyr.tidyverse.org/reference/dplyr-package.html) and [tidyr](https://tidyr.tidyverse.org/)
can help with `tidying` your data. --- background-image: url(data:image/png;base64,#https://github.com/allisonhorst/stats-illustrations/raw/main/rstats-artwork/tidydata_1.jpg) background-size: 95% 95% .footnote[ **Source:** Illustration is from the Openscapes blog [Tidy Data for reproducibility, efficiency, and collaboration](https://www.openscapes.org/blog/2020/10/12/tidy-data/) by Julia Lowndes and Allison Horst ] ??? * In database, this is schema. * Tidy data principles are a rephrase of third norm in a database schema design. <https://en.wikipedia.org/wiki/Third_normal_form>, to data scientists. * tidy data is for human consumption. * Tabular data is column-oriented format --- background-image: url(data:image/png;base64,#https://github.com/allisonhorst/stats-illustrations/raw/main/rstats-artwork/tidydata_2.jpg) background-size: contain .footnote[ **Source:** Illustration is from the Openscapes blog [Tidy Data for reproducibility, efficiency, and collaboration](https://www.openscapes.org/blog/2020/10/12/tidy-data/) by Julia Lowndes and Allison Horst ] --- # Grammar of Graphics Layers: Aesthetics **Aesthetics (`ggplot2::aes()`)** are used to make data visible. For example: - `x`, `y`: variable to be plotted along the x and y axes. - `color`: color of geoms (i.e., points, lines, etc) according to the data. - `fill`: the inside color of the geom (useful for bar charts). - `group`: what group a geom belongs to (useful in multiple ts). - `shape`: the shape of the plotted point (circle, triangle, filled circle, etc). - `linetype`: the type of line used (solid, dashed, etc). - `size`: size scaling for an extra dimension. - `alpha`: the transparency of the geom --- # Identify the Aesthetics Used in the Charts
−
+
08
:
00
.panelset[ .panel[.panel-name[Activity] > Over the next 8 minutes, please identify the aesthetics used in each chart. - Write down your answers in the right-side of each tab (it is editable). - You can discuss your answers with your neighboring classmates. - Be prepared to share these answers with class. ] .panel[.panel-name[Line Chart 1] .pull-left-2[ <img src="data:image/png;base64,#03_ts_viz_files/figure-html/retailsales_linechart1-1.png" width="100%" style="display: block; margin: auto;" /> ] .pull-right-2[ .can-edit.key-activity1a_viz[ **Main Aesthetics:** .font70[(Insert below)] - `x`: .... and its class is: .... - `y`: .... and its class is: .... - `group`: ..... - `color`: ..... ] ] ] .panel[.panel-name[Line Chart 2] .pull-left-2[ <img src="data:image/png;base64,#03_ts_viz_files/figure-html/retailsales_linechart2-1.png" width="100%" style="display: block; margin: auto;" /> ] .pull-right-2[ .can-edit.key-activity1b_viz[ **Main Aesthetics:** .font70[(Insert below)] - `x`: .... and its class is: .... - `y`: .... and its class is: .... - `group`: ..... - `color`: ..... ] ] ] .panel[.panel-name[Seasonal Chart 1] .pull-left-2[ <img src="data:image/png;base64,#03_ts_viz_files/figure-html/retailsales_linechart3-1.png" width="100%" style="display: block; margin: auto;" /> ] .pull-right-2[ .can-edit.key-activity1c_viz[ **Main Aesthetics:** .font70[(Insert below)] - `x`: .... and its class is: .... - `y`: .... and its class is: .... - `group`: ..... - `color`: ..... ] ] ] .panel[.panel-name[Seasonal Chart 2] .pull-left-2[ <img src="data:image/png;base64,#03_ts_viz_files/figure-html/retailsales_linechart4-1.png" width="100%" style="display: block; margin: auto;" /> ] .pull-right-2[ .can-edit.key-activity1d_viz[ **Main Aesthetics:** .font70[(Insert below)] - `x`: .... and its class is: .... - `y`: .... and its class is: .... - `group`: ..... - `color`: ..... ] ] ] ] --- # Grammar of Graphics Layers: Aesthetics - Assigned **globally** to the entire plot via `ggplot2::ggplot(ggplot2::aes())`, or to **specific geoms** (e.g., `ggplot2::geom_point(ggplot2::aes()).` .pull-left[ <div class="figure" style="text-align: center"> <img src="data:image/png;base64,#03_ts_viz_files/figure-html/global_aes-1.png" alt="The color is passed globally through ggplot(aes(x=date, y=price, color=year))." width="100%" /> <p class="caption">The color is passed globally through ggplot(aes(x=date, y=price, color=year)).</p> </div> ] .pull-right[ <div class="figure" style="text-align: center"> <img src="data:image/png;base64,#03_ts_viz_files/figure-html/local_aes-1.png" alt="The color is passed as an argument within the layer as geom_point(aes(color = year))." width="100%" /> <p class="caption">The color is passed as an argument within the layer as geom_point(aes(color = year)).</p> </div> ] --- # Grammar of Graphics Layers: Individual Geoms **Geometric objects** i.e., geoms help determine the type of plot. In this class, we will typically use one or more of the following *geoms*: - `ggplot2::geom_point()`: scatterplot or points in a line graph. - `ggplot2::geom_line()`: lines connecting points by increasing value of x. - `ggplot2::geom_smooth()`: to fit a function line (e.g., linear regression line) based on data. --- # Grammar of Graphics Layers: Facets We can use `ggplot2::facet_wrap()` to create small multiples based on a single variable. Arguments for `ggplot2::facet_wrap()` include: - `facets` which takes the variable of interest in quotes (i.e., `facets = 'symbol'`); - `nrow` and/or `ncol` which take numeric inputs for the number of rows and columns; and - `scales`, where we typically use `free_y` to denote that different `ylim` for each panel. ```r fang_df = tidyquant::tq_get( x = c('META', 'AMZN', 'NFLX', 'GOOG'), from = '2010-01-01', to = Sys.Date() ) colnames(fang_df) ``` ``` ## [1] "symbol" "date" "open" "high" "low" "close" "volume" ## [8] "adjusted" ``` --- count: false # Grammar of Graphics Layers: Facets We can use `ggplot2::facet_wrap()` to create small multiples based on a single variable. Arguments for `ggplot2::facet_wrap()` include: - `facets` which takes the variable of interest in quotes (i.e., `facets = 'symbol'`); - `nrow` and/or `ncol` which take numeric inputs for the number of rows and columns; and - `scales`, where we typically use `free_y` to denote that different `ylim` for each panel. .pull-left[ <img src="data:image/png;base64,#03_ts_viz_files/figure-html/faang_linechart-1.png" alt="A line chart of the FANG Closing Price Data." width="90%" style="display: block; margin: auto;" /> ] .pull-right[ <img src="data:image/png;base64,#03_ts_viz_files/figure-html/faang_multiples-1.png" alt="A panel chart of the FANG Closing Price Data." width="90%" style="display: block; margin: auto;" /> ] --- # Grammar of Graphics Layers: Coordinates In class, we will use the following two functions to create **snapshots** of the data: - `ggplot2::coord_cartesian()` to set limits. We will specicially use its xlim argument to create a snapshot when the `\(x\)` axis contains a continous variable (e.g., year). See [ggplot2 documentation](https://ggplot2.tidyverse.org/reference/coord_cartesian.html) for more detail. - `tidyquant::coord_x_date()` to set limits. We will specicially use its xlim argument to create a snapshot when the `\(x\)` axis contains a date variable (with a `class` of date). See [tidyquant documentation](https://business-science.github.io/tidyquant/reference/coord_x_date.html) for more detail. --- # Grammar of Graphics: Themes Themes control the overall visual defaults. There are some themes built within the `ggplot2`
(see the [complete themes guide](https://ggplot2.tidyverse.org/reference/ggtheme.html)). For additional themes, please feel free to play with the [ggthemes](https://github.com/jrnold/ggthemes)
. .pull-left[ <div class="figure" style="text-align: center"> <img src="data:image/png;base64,#03_ts_viz_files/figure-html/fang_theme1-1.png" alt="Default ggplot2 theme" width="100%" /> <p class="caption">Default ggplot2 theme</p> </div> ] .pull-right[ <div class="figure" style="text-align: center"> <img src="data:image/png;base64,#03_ts_viz_files/figure-html/fang_theme2-1.png" alt="A modified theme (no gridlines, no gray background and caption is place below)." width="100%" /> <p class="caption">A modified theme (no gridlines, no gray background and caption is place below).</p> </div> ] --- class: inverse, center, middle # Putting it all together --- # A Singular TS: AAPL's Adj. Close ```r if(require(tidyquant)==F) install.packages("tidyquant") # install if needed if(require(tidyverse)==F) install.packages('tidyverse') # install if needed aapl = # get AAPL stock data from 1st trading day after Jan 1, 2020 to now tidyquant::tq_get(x = 'AAPL', from = '2020-01-01', to = Sys.Date() ) |> # select (i.e., keep) only the variables below dplyr::select( c(date, symbol, adjusted) ) |> # create the following variables: year and month dplyr::mutate( # date has to be of class Date if not use lubridate::ymd (mdy, dmy, etc) # to convert the string variable to date year = lubridate::year(date), month = lubridate::month(date, label = T) ) tail(aapl, n = 1) # print the last obs to see what we have ``` ``` ## # A tibble: 1 × 5 ## date symbol adjusted year month ## <date> <chr> <dbl> <dbl> <ord> ## 1 2023-01-27 AAPL 146. 2023 Jan ``` --- # A Singular TS: The GG Layers .left-code[ .small[ ```r *# layers are + in ggplot2 *ggplot2::ggplot(aapl) ``` ] ] .right-plot[ <img src="data:image/png;base64,#03_ts_viz_files/figure-html/aapl1_out-1.png" width="100%" style="display: block; margin: auto;" /> ] --- count:false # A Singular TS: The GG Layers .left-code[ .small[ ```r # layers are + in ggplot2 ggplot2::ggplot( aapl, * ggplot2::aes(x = date, y = adjusted) ) ``` ] ] .right-plot[ <img src="data:image/png;base64,#03_ts_viz_files/figure-html/aapl2_out-1.png" width="100%" style="display: block; margin: auto;" /> ] --- count:false # A Singular TS: The GG Layers .left-code[ .small[ ```r # layers are + in ggplot2 ggplot2::ggplot( aapl, ggplot2::aes(x = date, y = adjusted) ) + * ggplot2::geom_point() ``` ] ] .right-plot[ <img src="data:image/png;base64,#03_ts_viz_files/figure-html/aapl3_out-1.png" width="100%" style="display: block; margin: auto;" /> ] --- count:false # A Singular TS: The GG Layers .left-code[ .small[ ```r # layers are + in ggplot2 ggplot2::ggplot( aapl, ggplot2::aes(x = date, y = adjusted) ) + ggplot2::geom_point( * ggplot2::aes(color = month) ) ``` ] ] .right-plot[ <img src="data:image/png;base64,#03_ts_viz_files/figure-html/aapl4_out-1.png" width="100%" style="display: block; margin: auto;" /> ] --- count:false # A Singular TS: The GG Layers .left-code[ .small[ ```r # layers are + in ggplot2 ggplot2::ggplot( aapl, ggplot2::aes(x = date, y = adjusted) ) + ggplot2::geom_point( ggplot2::aes(color = month) ) + * ggplot2::geom_line() ``` ] ] .right-plot[ <img src="data:image/png;base64,#03_ts_viz_files/figure-html/aapl5_out-1.png" width="100%" style="display: block; margin: auto;" /> ] --- count:false # A Singular TS: The GG Layers .left-code[ .small[ ```r # layers are + in ggplot2 ggplot2::ggplot( aapl, ggplot2::aes(x = date, y = adjusted) ) + ggplot2::geom_point( ggplot2::aes(color = month) ) + ggplot2::geom_line() + * ggplot2::geom_smooth( * method = lm, formula = 'y ~ x' * ) ``` ] ] .right-plot[ <img src="data:image/png;base64,#03_ts_viz_files/figure-html/aapl6_out-1.png" width="100%" style="display: block; margin: auto;" /> ] --- count:false # A Singular TS: The GG Layers .left-code[ .small[ ```r # layers are + in ggplot2 ggplot2::ggplot( aapl, ggplot2::aes(x = date, y = adjusted) ) + ggplot2::geom_point( ggplot2::aes(color = month) ) + ggplot2::geom_line() + ggplot2::geom_smooth( method = lm, formula = 'y ~ x' ) + * ggplot2::scale_x_date( * breaks = scales::pretty_breaks(n=8) * ) + * ggplot2::scale_y_continuous( * breaks = scales::pretty_breaks(n=6), * labels = scales::dollar) ``` ] ] .right-plot[ <img src="data:image/png;base64,#03_ts_viz_files/figure-html/aapl7_out-1.png" width="100%" style="display: block; margin: auto;" /> ] --- count:false # A Singular TS: The GG Layers .left-code[ .small[ ```r # layers are + in ggplot2 ggplot2::ggplot( aapl, ggplot2::aes(x = date, y = adjusted) ) + ggplot2::geom_point( ggplot2::aes(color = month) ) + ggplot2::geom_line() + ggplot2::geom_smooth( method = lm, formula = 'y ~ x' ) + ggplot2::scale_x_date( breaks = scales::pretty_breaks(n=8) ) + ggplot2::scale_y_continuous( breaks = scales::pretty_breaks(n=6), labels = scales::dollar) + * tidyquant::coord_x_date( * xlim = c('2023-01-01', '2023-01-31') * ) ``` ] ] .right-plot[ <img src="data:image/png;base64,#03_ts_viz_files/figure-html/aapl8_out-1.png" width="100%" style="display: block; margin: auto;" /> ] --- count:false # A Singular TS: The GG Layers .left-code[ .small[ ```r # layers are + in ggplot2 ggplot2::ggplot( aapl, ggplot2::aes(x = date, y = adjusted) ) + ggplot2::geom_point( ggplot2::aes(color = month) ) + ggplot2::geom_line() + ggplot2::geom_smooth( method = lm, formula = 'y ~ x' ) + ggplot2::scale_x_date( breaks = scales::pretty_breaks(n=8) ) + ggplot2::scale_y_continuous( breaks = scales::pretty_breaks(n=6), labels = scales::dollar) + tidyquant::coord_x_date( xlim = c('2023-01-01', '2023-01-31') ) + * ggplot2::theme_bw(base_size = 14) + * ggplot2::theme( * legend.position = 'bottom' * ) ``` ] ] .right-plot[ <img src="data:image/png;base64,#03_ts_viz_files/figure-html/aapl9_out-1.png" width="100%" style="display: block; margin: auto;" /> ] --- count:false # A Singular TS: The GG Layers .left-code[ .small[ ```r # layers are + in ggplot2 ggplot2::ggplot( aapl, ggplot2::aes(x = date, y = adjusted) ) + ggplot2::geom_point( ggplot2::aes(color = month) ) + ggplot2::geom_line() + ggplot2::geom_smooth( method = lm, formula = 'y ~ x' ) + ggplot2::scale_x_date( breaks = scales::pretty_breaks(n=8) ) + ggplot2::scale_y_continuous( breaks = scales::pretty_breaks(n=6), labels = scales::dollar) + tidyquant::coord_x_date( xlim = c('2023-01-01', '2023-01-31') ) + ggplot2::theme_bw(base_size = 14) + ggplot2::theme( legend.position = 'bottom' * ) -> aapl_plot *plotly::ggplotly(p = aapl_plot) ``` ] ] .right-plot[
] --- # So How to Handle `ts()` Objects? .pull-left[ .small[ ```r forecast::autoplot(JohnsonJohnson) ``` <img src="data:image/png;base64,#03_ts_viz_files/figure-html/jj_forecast_plot-1.png" width="70%" style="display: block; margin: auto;" /> ] ] .pull-right[ .small[ ```r jj_df = data.frame( date = zoo::as.Date(x = time(JohnsonJohnson)), earnings = JohnsonJohnson ) ggplot2::ggplot( jj_df, ggplot2::aes(x = date, y = earnings) ) + ggplot2::geom_line() ``` <img src="data:image/png;base64,#03_ts_viz_files/figure-html/jj_ggplot-1.png" width="70%" style="display: block; margin: auto;" /> ] ] --- # Multiple TS: A Demo Let us build a panel seasonal plot of your choice with FRED data. --- class: inverse, center, middle # Recap --- # Summary of Main Points By now, you should be able to do the following: - Examine a line chart for trends, seasonality, and cycles. - Explain the grammar of graphics and how it can be used to create time series plots in
. - Create interactive time-series plots by using the [plotly](https://plotly.com/ggplot2/getting-started/) package
. --- # Things to Do to Prepare for Our Next Class - Go over your notes, read the **references below**, and **complete** the [self-paced R tutorial](http://rstudio.fsb.miamioh.edu:3838/megahefm/isa444/spring2023/datatypes/). - Complete [Assignment 02](https://miamioh.instructure.com/courses/188655/assignments/2368786) and [Assignment 03](https://miamioh.instructure.com/courses/188655/quizzes/539069/) on Canvas. .pull-left[ .center[[<img src="https://d33wubrfki0l68.cloudfront.net/b88ef926a004b0fce72b2526b0b5c4413666a4cb/24a30/cover.png" height="350px">](https://r4ds.had.co.nz)] ] .pull-right[ * [Data Visualization](https://r4ds.had.co.nz/data-visualisation.html) * [Graphics for Communication](https://r4ds.had.co.nz/graphics-for-communication.html) * [Dates and Times](https://r4ds.had.co.nz/dates-and-times.html) ]